home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d14 / actortut.arc / TUTR2.TXT < prev    next >
Text File  |  1990-10-18  |  6KB  |  167 lines

  1.                                 Actor Tutorial
  2.                                 --------------
  3.  
  4. Copyright (c) 1989 The Whitewater Group, Inc.
  5.  
  6. Notes on Dictionaries
  7. ---------------------  
  8. One of the most powerful features of Actor(R) is the Dictionary class.  A
  9. dictionary is a collection of key/element pairs, called associations.  While
  10. arrays in Actor and other languages limit you to integer keys, an Actor
  11. dictionary can use any object for its keys.  The dictionary is a lookup table
  12. that gives you an element given a key to that element.  Unlike English
  13. language dictionaries, an Actor dictionary has no inherit order.
  14.  
  15. Basic messages that a dictionary understands include add, at, and remove.
  16. Try the following:
  17.   
  18. First, create a dictionary of size 3 with a new message:
  19.   
  20.   Locale := new(Dictionary, 3); <CR>
  21.   
  22. This is only an initial size; dictionaries automatically grow as you add
  23. elements.
  24.  
  25. Add two associations to the dictionary, "Here"->"Belize" and
  26. "There"->"Akron."  In this example, "Here" and "There" are the keys; "Belize"
  27. and "Akron" are the elements:
  28.   
  29.   add(Locale, "Here", "Belize"); <CR>
  30.   add(Locale, "There", "Akron"); <CR>
  31.   
  32. Now find what element is referenced by the key "There":
  33.   
  34.   at(Locale, "There"); <CR>
  35.   
  36. Finally, remove the association at "Here":
  37.   
  38.   remove(Locale, "Here"); <CR>
  39.   
  40. You will notice that at and add messages return the element; remove returns
  41. the key.  You can examine the dictionary as you alter it by typing Locale in
  42. the workspace or by using an inspector.
  43.  
  44. There is a syntactic shorthand for sending add and at messages: the
  45. familiar "[ ]" notation used with arrays.
  46.   
  47.   The message...                     Is equivalent to...
  48.   
  49.   add(Locale, "There", "Akron")      Locale["There"] := "Akron"
  50.   X := at(Locale, "Here")            X := Locale["Here"]
  51.   
  52. In the above example, both the keys and elements are strings.  Remember
  53. that any object can be a key and any object can be an element in a
  54. dictionary.  You may want to use arbitrary integers or characters as keys.
  55. You may want to have Point objects, strings, or even other dictionaries as
  56. elements.
  57.  
  58. You can do much more than send add, at, and remove messages to a
  59. dictionary; Actor gives you the power to perform operations on each item of a
  60. dictionary.  The do methods enumerate over every element of a collection; in
  61. other words, a do returns a value for each entry in turn, allowing you to
  62. perform a set of operations on each.  There are three do messages which are
  63. sent to dictionaries: do, keysDo, and assocsDo.  Each operates in a slightly
  64. different fashion, as shown here.
  65.  
  66.     Recreate the Locale dictionary used above for these examples:
  67.     
  68.     Locale["Here"] := "Belize"; <CR>
  69.     Locale["There"] := "Akron";    <CR>
  70.     
  71.   do
  72.     
  73.     Enumerate each element in the dictionary:
  74.     
  75.     do(Locale, {using(anElem) printLine(anElem)}); <CR>
  76.     
  77.     The display reads:
  78.     
  79.     Belize
  80.     Akron
  81.     
  82.   keysDo
  83.     
  84.     Enumerate each key in the dictionary:
  85.     
  86.     keysDo(Locale, {using(aKey) printLine(aKey)}); <CR>
  87.     
  88.     The display reads:
  89.     
  90.     Here
  91.     There
  92.     
  93.   assocsDo
  94.     
  95.     Enumerate each key/element pair in the dictionary:
  96.     
  97.     assocsDo(Locale, {using(anAssoc) printLine(anAssoc)}); <CR>
  98.     
  99.     The display reads:
  100.     
  101.     "Here"->"Belize"
  102.     "There"->"Akron"
  103.     
  104.     This indicates that the entire association was returned with assocsDo.
  105.     
  106.   When using the various do methods, it is helpful to use a meaningful name
  107. for the temporary variable; in this case, aKey, anElem, and anAssoc were used
  108. as a reminder of their contents.
  109.   You may find it useful to locate elements within a dictionary based on only
  110. a portion of the key.  We'll use keysDo to implement matchKeys.  To add it to
  111. your system, select the Dictionary class from the browser, enter the code,
  112. and accept.
  113.     
  114.     /* Return a set of all keys that begin with a String */
  115.     Def matchKeys(self, aStr | aSet)
  116.     {  aSet := new(Set, 10);
  117.        aStr := asString(aStr);
  118.        keysDo(self,
  119.           {using(aKey)
  120.              if subString(asString(aKey), 0, size(aStr)) = aStr
  121.  
  122.               add(aSet, aKey)
  123.            endif;
  124.         });
  125.      ^aSet
  126.   }
  127.   
  128.   This method will work with any dictionary having string or symbol keys.
  129. With matchKeys you could find every Actor constant beginning with MF_ (these
  130. are Windows(tm) constants):
  131.   
  132.   matchKeys(Constants, "MF_"); <CR>
  133.   
  134.   Extract is another powerful method available to a dictionary.  Extract
  135. evaluates a block for each element of the dictionary; if the result is true
  136. (not nil), the key/element pair will be added to a new dictionary.
  137.   Since the values within a dictionary can be objects of different classes,
  138. you may want to create a sub-dictionary containing only values of a specific
  139. class.  We'll use extract to implement this:
  140.   
  141.   /*  Return a new Dictionary containing only those
  142.       associations where the class of value is cl   */
  143.   Def matchClass(self, cl)
  144.   {  ^extract(self,
  145.         {using(elem)
  146.            class(elem) = cl
  147.         })
  148.   }
  149.   
  150.   One use of matchClass is to find all global variables of a given class, for
  151. instance:
  152.   
  153.   matchClass(Actor, Int); <CR>
  154.   
  155.   Try developing a matchValue method that returns a set of all keys which
  156. point to a specified element.  This method is very useful when developing
  157. Microsoft Windows menus; with it you can verify that there are no clashes
  158. between your menu item constants.  Try writing the method again to return a
  159. dictionary instead.
  160.   By incorporating dictionaries into your own applications you will often
  161. decrease development time and increase program speed.  If you have developed
  162. any useful methods for the Dictionary class, or have used the class in
  163. interesting ways, please share your experiences here on the BBS.
  164.  
  165. Actor is a registered trademark of The Whitewater Group, Inc.  Other product
  166. names may be trademarks of their respective owners.